#ifndef __INCLUDE_H_
#define __INCLUDE_H_

#include <gtk/gtk.h>
#include <math.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/time.h>

struct regional
{
	float ax;
	float ay;
	int par_num;
};

typedef struct
{
	float x;  // 粒子的x坐标
	float y;  // 粒子的y坐标
	float vx; // 粒子的x速度
	float vy; // 粒子的y速度
	float ax; // 粒子的x加速度
	float ay; // 粒子的y加速度
	float R;  // 粒子的红色值
	float G;  // 粒子的绿色值
	float B;  // 粒子的蓝色值
} Particle;

#define TH_MAX 256			 // 最大线程数量
#define TH_NUM 14			 // 默认线程数量
#define PAR_R 6				 // 粒子半径
#define PAR_NUM 2000		 // 默认粒子数量
#define MAX_A 2000			 // 最大加速度限制
#define GridRatio 32		 // 网格缩小比例
#define WIN_W 38 * GridRatio // 画布宽度
#define WIN_H 28 * GridRatio // 画布高度
#define TIME_DT 0.01		 // 时间颗粒度
// #define SHOW_Gravi_Line
#define LIMIT(x, min, max) ((x) > (max) ? max : ((x) < (min) ? (min) : (x)))

#define REGIONAL_X ((WIN_W / GridRatio))
#define REGIONAL_Y ((WIN_H / GridRatio))
extern struct regional regionals[REGIONAL_Y][REGIONAL_X];

extern Particle particles[1024 * 16]; // 懒得去malloc了 反正半中间还有新加粒子
extern GtkWidget *drawing_area;		  // 绘图区域指针
extern float xa_g;					  // 环境重力
extern float ya_g;					  // 环境重力
extern int par_num;					  // 粒子数量

extern pthread_mutex_t th_mutex[TH_MAX]; // 计算加速度线程 同步 互斥锁
extern pthread_cond_t th_cond[TH_MAX];	 // 计算加速度线程 同步 信号
extern volatile int th_flag[TH_MAX];	 // 计算加速度线程 同步 标志

extern pthread_mutex_t mutex0;		   // 计算速度位置线程 同步 互斥锁
extern pthread_cond_t cond0;		   // 计算速度位置线程 同步 信号
extern volatile int flag0;			   // 计算速度位置线程 同步 标志
extern volatile unsigned int run_cnt0; // 计算速度位置线程 计数
extern int th_num;

void par_init(void);
void thread_init(void);
void gtk_ui_init(int argc, char *argv[]);

void calculate_location(void);
void calculate_regional_acc(void);
void *thread_cmd(void *thread_id);
void *thread_location(void *thread_id);
void *thread_acceleration(void *thread_id);
void calculate_acceleration(int start, int end);
void calculate_exclusion(float dx, float dy, float distance_2, float distance, Particle *particle);

gboolean update_fps(gpointer data);
gboolean update_particles(gpointer data);
gboolean draw_callback(GtkWidget *widget, cairo_t *cr, gpointer data);
gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data);
gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data);
#endif //__INCLUDE_H_